﻿/*
 * Author:  hammer
 * CreateTime: 2018/9/30 16:32:34
 * Module: UniEngine
 * 主要功能：MGAudio的UniEngine管理类 单例模式
 *
 */
using UnityEngine;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
using System.Collections;
using MGFramework;
using Mumble;

namespace MGAudioEngine.UniEngine
{
    [RequireComponent(typeof(EventProcessor))]
    public class UniEngineManager : MonoBehaviour
    {
        public GameObject UniAudioPlayerPrefab;
        public MumbleMicrophone UniMicrophone;
        public DebugValues DebuggingVariables;

        private MumbleClient _mumbleClient;
        public bool ConnectAsyncronously = true;
        public string HostName = "116.62.125.243";
        public int    Port     = 64738;
        public string Username = "ExampleUser";
        public string Password = "1passwordHere!";
        public string ChannelToJoin = "";

        void Start()
        {
            HostName = "116.62.125.243";
            Username = "mumbleunity";
            Port = 24349;
            Password = "dbc0be36";

            if (HostName == "1.2.3.4")
            {
                Debuger.LogError("Please set the mumble host name to your mumble server");
                return;
            }
            Application.runInBackground = true;
            _mumbleClient = new MumbleClient(HostName, Port, CreateMumbleAudioPlayerFromPrefab, DestroyMumbleAudioPlayer, ConnectAsyncronously, SpeakerCreationMode.ALL, DebuggingVariables);

            //if (DebuggingVariables.UseRandomUsername)
            //    Username += UnityEngine.Random.Range(0, 100f);

            if (ConnectAsyncronously)
                StartCoroutine(ConnectAsync());
            else
            {
                _mumbleClient.Connect(Username, Password);
                if (UniMicrophone != null)
                    _mumbleClient.AddMumbleMic(UniMicrophone);
            }

#if UNITY_EDITOR
            if (DebuggingVariables.EnableEditorIOGraph)
            {
                EditorGraph editorGraph = EditorWindow.GetWindow<EditorGraph>();
                editorGraph.Show();
                StartCoroutine(UpdateEditorGraph());
            }
#endif
        }

        IEnumerator ConnectAsync()
        {
            while (!_mumbleClient.ReadyToConnect)
                yield return null;
            Debug.Log("Will now connect");
            _mumbleClient.Connect(Username, Password);
            yield return null;
            if (UniMicrophone != null)
                _mumbleClient.AddMumbleMic(UniMicrophone);
        }

        //创建玩家音源
        private MumbleAudioPlayer CreateMumbleAudioPlayerFromPrefab(string username, uint session)
        {
            // Depending on your use case, you might want to add the prefab to an existing object (like someone's head)
            // If you have users entering and leaving frequently, you might want to implement an object pool
            GameObject newObj = GameObject.Instantiate(UniAudioPlayerPrefab);
            newObj.name = username + "_MumbleAudioPlayer";
            MumbleAudioPlayer newPlayer = newObj.GetComponent<MumbleAudioPlayer>();
            Debug.Log("Adding audio player for: " + username);
            return newPlayer;
        }

        //销毁玩家音源
        private void DestroyMumbleAudioPlayer(uint session, MumbleAudioPlayer playerToDestroy)
        {
            UnityEngine.GameObject.Destroy(playerToDestroy.gameObject);
        }
        void OnApplicationQuit()
        {
            Debug.LogWarning("Shutting down connections");
            if (_mumbleClient != null)
                _mumbleClient.Close();
        }
        IEnumerator UpdateEditorGraph()
        {
            long numPacketsReceived = 0;
            long numPacketsSent = 0;
            long numPacketsLost = 0;

            while (true)
            {
                yield return new WaitForSeconds(0.1f);

                long numSentThisSample = _mumbleClient.NumUDPPacketsSent - numPacketsSent;
                long numRecvThisSample = _mumbleClient.NumUDPPacketsReceieved - numPacketsReceived;
                long numLostThisSample = _mumbleClient.NumUDPPacketsLost - numPacketsLost;

                Graph.channel[0].Feed(-numSentThisSample);//gray
                Graph.channel[1].Feed(-numRecvThisSample);//blue
                Graph.channel[2].Feed(-numLostThisSample);//red

                numPacketsSent += numSentThisSample;
                numPacketsReceived += numRecvThisSample;
                numPacketsLost += numLostThisSample;
            }
        }

        void Update()
        {
            if (!_mumbleClient.ReadyToConnect)
                return;
            if (Input.GetKeyDown(KeyCode.S))
            {
                _mumbleClient.SendTextMessage("This is an example message from Unity");
                print("Sent mumble message");
            }
            if (Input.GetKeyDown(KeyCode.J))
            {
                print("Will attempt to join channel " + ChannelToJoin);
                _mumbleClient.JoinChannel(ChannelToJoin);
            }
        }
    }
}

